//
//  DocumentCamera.swift
//  Scaner
//
//  Created by liyahao on 2025/4/8.
//

import SwiftUI
import VisionKit
import Combine

typealias CameraResult = Result<VNDocumentCameraScan, Error>
typealias CancelAction = () -> Void
typealias ResultAction = (CameraResult) -> Void

struct ScanDocumentView: UIViewControllerRepresentable {
    private let cancelAction: CancelAction
    private let resultAction: ResultAction
    
    init(cancelAction: @escaping CancelAction = {}, resultAction: @escaping ResultAction) {
        self.cancelAction = cancelAction
        self.resultAction = resultAction
    }
    
    public func makeCoordinator() -> Coordinator {
        Coordinator(cancelAction: cancelAction, resultAction: resultAction)
    }
    
    public func makeUIViewController(context: Context) -> VNDocumentCameraViewController {
        let controller = VNDocumentCameraViewController()
        controller.delegate = context.coordinator
        return controller
    }
    
    public func updateUIViewController(_ uiViewController: VNDocumentCameraViewController, context: Context) {
        
    }
    
    class Coordinator: NSObject, VNDocumentCameraViewControllerDelegate {
        private let cancelAction: CancelAction
        private let resultAction: ResultAction
        
        public init(cancelAction: @escaping CancelAction, resultAction: @escaping ResultAction) {
            self.cancelAction = cancelAction
            self.resultAction = resultAction
        }
        
        public func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) {
            cancelAction()
            controller.dismiss(animated: true, completion: nil)
        }
        
        public func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFailWithError error: Error) {
            resultAction(.failure(error))
        }
        
        public func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
            resultAction(.success(scan))
            controller.dismiss(animated: true, completion: nil)
        }
    }
}
